/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is NetBeans. The Initial Developer of the Original
* Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
* Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.modules.jarpackager.util;
import java.util.HashSet;
import java.util.Iterator;
import java.io.File;
import java.io.IOException;
import java.util.jar.JarFile;
import java.util.Enumeration;
import java.beans.PropertyVetoException;
import java.text.MessageFormat;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileSystem;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.util.NbBundle;
import org.netbeans.modules.jarpackager.JarContent;
import org.netbeans.modules.jarpackager.options.JarPackagerOption;
/** Responsibility of this class is to inspect given
* jar archive, inspect it and produce resulting instance of
* JarContent which describes content of the archive.
* Also allows for listening to the inspecting progress.
*
* @author Dafe Simonek
*/
public class JarInspector extends Object {
/** Message format for progress information */
private static MessageFormat progressInfo;
/** Constant for meta information directory */
private static final String META_INF_DIR = "META-INF"; // NOI18N
/** set of progress listeners
* @associates ProgressListener*/
private HashSet listeners;
/** jar archive to inspect */
private File archiveFile;
/** Creates new JarInspector with given jat file. */
public JarInspector (File archiveFile) {
this.archiveFile = archiveFile;
}
/** Incpects asociated archive and creates new jar content
* describing it.
* @return newly created jarcontent instance which describes
* asociated jar archive.
*/
public JarContent createContent ()
throws IOException, PropertyVetoException {
// obtain count of files in the archive
JarFile jarFile = new JarFile(archiveFile);
long itemCount = jarFile.size();
// obtain the manifest from the archive
JarContent result = new JarContent();
initializeFromOptions(result);
fireProgressEvent(0, "MSG_ObtainingManifest"); // NOI18N
result.setManifest(jarFile.getManifest());
jarFile.close();
// make garbage collectable
jarFile = null;
// target file
result.setTargetFile(archiveFile);
// don't filter anything
result.setFilter(JarContent.ALL);
// add to repository (if it's not here already)
fireProgressEvent(0, "MSG_AddingToRepository"); // NOI18N
FileSystem jarFs = JarUtils.addJarFSToRepository(archiveFile, false);
// go through the archive entries and build jar content
FileObject curFo = null;
long counter = 0;
for (Enumeration enum = jarFs.getRoot().getChildren(false);
enum.hasMoreElements(); counter++) {
curFo = (FileObject)enum.nextElement();
try {
// add all but meta inf dir
if (!META_INF_DIR.equals(curFo.getName())) {
result.putFile(DataObject.find(curFo).getPrimaryFile());
}
} catch (DataObjectNotFoundException exc) {
// we can silently ignore the exception, because
// it means that file object is not recognized by any loader
// and as such will not be visible in repository
if (System.getProperty("netbeans.debug.exceptions") != null) {
exc.printStackTrace();
}
}
// notify progress listeners
fireProgressEvent(
(int)(counter * 100 / itemCount),
progressInfo().format( new Object[] { curFo.getName() } )
);
}
return result;
}
/* Adds new listener which will be notified about creating progress.
* @param pl new listener
*/
public synchronized void addProgressListener (ProgressListener pl) {
if (listeners == null)
listeners = new HashSet();
listeners.add(pl);
}
/* Removes specified listener from the listener list.
* @param pl listener to remove
*/
public synchronized void removeProgressListener (ProgressListener pl) {
if (listeners == null)
return;
listeners.remove(pl);
}
/** Fires notification about creating progress.
* @param pe progress event to fire off
*/
protected void fireProgressEvent (int percent, String description) {
if (listeners == null)
return;
HashSet cloned;
// clone listener list
synchronized (this) {
cloned = (HashSet)listeners.clone();
}
// fire on cloned list to prevent from modifications when firing
for (Iterator iter = cloned.iterator(); iter.hasNext(); ) {
((ProgressListener)iter.next()).progress(percent, description);
}
}
/** Utility method, initializes given jar content with respect
* to the current jar packager options values.
*/
private static void initializeFromOptions (JarContent jc) {
JarPackagerOption rootOption = JarPackagerOption.singleton();
jc.setCompressed(rootOption.isCompressed());
jc.setCompressionLevel(rootOption.getCompressionLevel());
jc.setManifestFileList(rootOption.isManifestFileList());
jc.setMainAttributes(rootOption.isMainAttributes());
}
/** Getter for progress info message */
private static MessageFormat progressInfo () {
// message format for progress message
if (progressInfo == null) {
progressInfo = new MessageFormat(
NbBundle.getBundle(JarInspector.class).getString("FMT_ProgressInfo")
);
}
return progressInfo;
}
}
/*
* <<Log>>
* 4 Gandalf 1.3 1/16/00 David Simonek i18n
* 3 Gandalf 1.2 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun
* Microsystems Copyright in File Comment
* 2 Gandalf 1.1 10/5/99 David Simonek various fixes, only
* primary entries now resides in 'chosen content'
* 1 Gandalf 1.0 10/4/99 David Simonek
* $
*/